#ifndef FOREST_H
#define FOREST_H

#include <iostream>
#include"Tree.h"

template <class S>
class MyCircleDistanceFunctor
{
public:
    template <class CIRCLETYPE, class SCALARTYPE>

    inline bool operator () (const CIRCLETYPE &c0, const CIRCLETYPE & c, SCALARTYPE & minDist, CIRCLETYPE & cr)
    {
        // Retour de la distance p-p0
        SCALARTYPE d = (SCALARTYPE) Distance(c0.getCenter(), c.getCenter()) ;

        // Atteinte en c
        cr = c;

        // Test de d < minDist
        bool ret ;

        if (d < minDist)
            ret = 1 ;
        else
            ret = 0 ;

        // Retour de la distance minimale dans d
        minDist = d ;

        return (ret);
    }
};

class Forest
{
private:
    vector<Tree *> forest ;
    list<CircleTree *>::iterator findCircleInList(CircleTree *c, list<CircleTree *> rslt) ;

public:
    Forest() ;
    inline ~Forest() {}

    inline unsigned int size() { return forest.size(); }

    // ************************** Tree creation / manipulation **************************
    void addCircleTreeBot (Tree *t, CircleTree *c) ;
    void createForest (vector<CircleTree> *rslt_p, vcg::GridStaticPtr<CircleTree, float> *grid_circ, float r_max, float h_max, float maxPfeiferDist, int distanceType) ;

    // ************************** Filtering *********************** //
    void filterTreesOnSize ( unsigned int threshold );

    // ************************** Output **************************
    void traverseForest () ;
    void drawForest (MeshDocument &m, bool draw_circles = false) ;

    /*!
     * \brief getTree
     *
     * Renvoie un pointeur vers l'arbre stocke a un certain index dans le tableau d'arbres de la foret
     *
     * \param vectorIndex : indice de l'arbre dans le vecteur d'arrbes
     * \return un pointeur vers l'arbre stocke a l'index vectorIndex du vecteur d'arbre de la foret
     */
    inline Tree* getTree ( unsigned int vectorIndex ) {return forest[vectorIndex]; }
};

#endif // FOREST_H
